using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using CNRegex.Dal;
using CNRegex.Enum;
using System.Linq.Expressions;
using NHibernate.Type;
using Project.Common;

namespace CNRegex.Biz
{
		public class BaseBiz<T, U> : IBiz<T>
		where T : class
		where U : Repository<T>
	{
		protected static U dbAccess;
		public BaseBiz()
		{
			dbAccess = DalFactory.Get<U>();
            dbAccess.Inject();
		}

		public virtual T GetByID<TInput>(TInput id)
		{
			return dbAccess.GetByID(id);
		}

		public virtual IList<T> PaginateList(int? pageSize, int? pageIndex, ref int count, Expression<Func<T, object>> path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.PaginateList(pageSize, pageIndex, ref count, path, direction);
		}

		/// <summary>
		/// 分页查询
		/// </summary>
		/// <param name="pageSize"></param>
		/// <param name="pageIndex"></param>
		/// <param name="count"></param>
		/// <param name="criteria"></param>
		/// <param name="path">Property Expression</param>
		/// <param name="direction"></param>
		/// <returns></returns>
		public virtual IList<T> PaginateListBy(int? pageSize, int? pageIndex, ref int count, Expression<Func<T, bool>> criteria, Expression<Func<T, object>> path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.PaginateListBy(pageSize, pageIndex, ref count, criteria, path, direction);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="pageSize"></param>
		/// <param name="pageIndex"></param>
		/// <param name="count"></param>
		/// <param name="criteria"></param>
		/// <param name="path">Property Name</param>
		/// <param name="direction"></param>
		/// <returns></returns>
		public virtual IList<T> PaginateListBy(int? pageSize, int? pageIndex, ref int count, Expression<Func<T, bool>> criteria, string path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.PaginateListBy(pageSize, pageIndex, ref count, criteria, ReflectionTools.GetClassPropertyExpression<T>(path), direction);
		}

		public virtual IList<T> List(System.Linq.Expressions.Expression<Func<T, object>> path = null, Enum.EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.List(path, direction);
		}

		public virtual IList<T> ListIn<U>(IList<U> collection, Expression<Func<T, object>> property)
		{
			return dbAccess.ListIn(collection, property);
		}

		public virtual IList<T> ListBy(System.Linq.Expressions.Expression<Func<T, bool>> criteria, System.Linq.Expressions.Expression<Func<T, object>> path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.ListBy(criteria, path, direction);
		}

		public virtual IList<T> ListBy(System.Linq.Expressions.Expression<Func<T, bool>> criteria, string path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.ListBy(criteria, ReflectionTools.GetClassPropertyExpression<T>(path), direction);
		}

		public virtual IList<T> ListTopX(Expression<Func<T, bool>> criteria, int count, Expression<Func<T, object>> path = null, EnumOrder direction = EnumOrder.ASC)
		{
			return dbAccess.ListTopX(criteria, count, path, direction);
		}

		public T GetFirst(Expression<Func<T, bool>> criteria, Expression<Func<T, object>> path = null, EnumOrder direction = EnumOrder.ASC)
		{
			var list = ListBy(criteria, path, direction);
			if (list.Count > 0)
				return list[0];
			return null;
		}

		public virtual void Save(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.Save(entity);
				tx.Commit();
			}
		}

		public virtual void Update(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.Update(entity);
				tx.Commit();
			}
		}

		public virtual void Delete(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.Delete(entity);
				tx.Commit();
			}
		}

		public virtual void SaveOrUpdate(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.SaveOrUpdate(entity);
				tx.Commit();
			}
		}

		public virtual T Merge(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			T t = default(T);
			using (tx)
			{
				t = dbAccess.Merge(entity);
				tx.Commit();
			}
			return t;
		}

		public virtual void Persist(T entity)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.Persist(entity);
				tx.Commit();
			}
		}


		public void DeleteByID<TInput>(TInput id, NullableType nullableType)
		{
			ITransaction tx = dbAccess.Session.BeginTransaction();
			using (tx)
			{
				dbAccess.DeleteByID(id, nullableType);
				tx.Commit();
			}
		}

		//public static TIn InvokeConstructor<TIn>()
		//{
		//    Type t = typeof(TIn);
		//    Type st = typeof(ISession);
		//    ConstructorInfo constructInfo = t.GetConstructor(new Type[] { st });
		//    DynamicMethod dynamicmethod = new DynamicMethod("", t, new Type[] { st });
		//    ILGenerator il = dynamicmethod.GetILGenerator();
		//    il.Emit(OpCodes.Ldarg_0);
		//    il.Emit(OpCodes.Newobj, constructInfo);
		//    il.Emit(OpCodes.Ret);
		//    Func<ISession, TIn> fun = dynamicmethod.CreateDelegate(typeof(Func<ISession, TIn>)) as Func<ISession, TIn>;
		//    TIn o = fun(session);
		//    return o;
		//}

	}
}
